//
// reqengine - reqengine source code.
//
// $Rev$
// $Author$
// $Date$
//
// Define class Request.
//

#ifndef __REQUEST__H
#define __REQUEST__H

#include <map>

#ifdef _POOL_ALLOC
#include <ext/pool_allocator.h>
#endif

#include "core/base/auto_mutex.h"
#include "core/base/mutex.h"
#include "core/base/noncopyable.h"
#include "core/base/types.h"

using namespace core;

namespace reqengine {

class TCPConnection;
class RequestContent;
class ResponseContent;

class Request : public Noncopyable {
#ifdef _POOL_ALLOC
  typedef __gnu_cxx::__pool_alloc<ValuePair> PoolAllocator;
  typedef std::map<uint64, Request *, PoolAllocator> SubRequestMap;
#else
  typedef std::map<uint64, Request *> SubRequestMap;
#endif

 public:
  Request() : id_(0), parent_id_(0), request_(NULL),
         request(NULL), nonresponse_num_(0) {}
  ~Request() {}

  inline void Initialize(TCPConnection *connection) { this->connection_ = connection; }
  inline TCPConnection *GetConnection() { return this->connection_; }

  inline void SetRequestContent(RequestContent *content) { this->request_ = content; }

  inline void AllocateID(uint64 id) { this->id_ = id; }
  inline uint64 GetID() const { return this->id_; }

  inline void SetParentID(uint64 id) { this->parent_id_ = id; }
  inline uint64 GetParentID() const { return this->parent_id_; }

  inline uint32 GetNonresponseNum() const { return this->nonresponse_num_; }
  inline bool CheckFinishResponse() const { return this->nonresponse_num_ == 0; }

  inline const RequestContent *GetRequestContent() const { return this->request_; }
  inline const ResponseContent *GetResponseContent() const { return this->response_; }

  inline bool CheckIsChild(uint64 id) const {
         return this->sub_requests_.find(id) != this->sub_requests_.end();
  }

  void Recycle();

  // Divide sub request.
  void Divide();
  // Request.
  void Requesting();
  // Response.
  void Responsing(ResponseContent *content);
  // Map to calculate request.
  void Map();
  // Reduce to Merger response.
  void Reduce();

 private:
  inline void Increase() {
    ++this->nonresponse_num_;
  }
  inline void Decrease() {
    if(this->nonresponse_num_ > 0)
      --this->nonresponse_num_;
  }

  uint64 id_;
  uint64 parent_id_;

  RequestContent *request_;
  ResponseContent *response_;

  uint32 nonresponse_num_;
  SubRequestMap sub_requests_;

  mutable Mutex mutex_;
};

}  // namespace reqengine

#endif  // __REQUEST__H

